perm filename SYMBOL.SAI[PNT,HE]8 blob
sn#531962 filedate 1980-08-26 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00010 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 ENTRY
C00004 00003 ! recover
C00006 00004 ! symbol table: check,checktot,ensym,delsym,newsym,oldsym
C00017 00005 ! symbol table: mk_pr, mk_rec, mk_sym, symtree routines
C00024 00006 ! symbol table: gtframe,checkoff,arrydim
C00027 00007 ! symbol table: nwr,dcdsym,unlink,linkfr,nwarec
C00033 00008 ! symbol table: control,insertion,prdecl
C00039 00009 ! symbol table: killtree,killvar,reset
C00043 00010 ! affixes the frame pointed by n to the frame pointed by d, as indicated
C00044 ENDMK
C⊗;
ENTRY;
BEGIN "SYMBOL"
DEFINE $SYMBOL=TRUE;
REQUIRE "HEADER.SAI" SOURCE_FILE;
REQUIRE "⊂⊃⊂⊃" DELIMITERS;
DEFINE NVAL=0;
REDEFINE XX(A)=⊂ redefine nval=nval + a; nval ⊃;
REQUIRE "AIDEFS.SAI" SOURCE_FILE;
PRELOAD_WITH NVAL,XX(NO_OF_SCALARS),XX(NO_OF_VECTORS),XX(NO_OF_TRANSES),
XX(NO_OF_TRANSES),XX(NO_OF_TRANSES),XX(NO_OF_EVENTS),
XX(NO_OF_STRINGS),XX(NO_OF_CM),XX(NO_OF_MACROS),
XX(NO_OF_FUNCTIONS);
INTEGER ARRAY ARR0[1:11];
PRELOAD_WITH NO_OF_SCALARS,NO_OF_VECTORS,NO_OF_TRANSES,NO_OF_TRANSES,
NO_OF_TRANSES,NO_OF_EVENTS,NO_OF_STRINGS,NO_OF_CM,
NO_OF_MACROS,NO_OF_FUNCTIONS;
INTEGER ARRAY ARR1[1:10]; ! maximum offsets and sizes ;
RPTR(SYMBOL)ARRAY SYMBOL_TABLE[1:NVAL];
INTERNAL RPTR(SYMBOL) PROCEDURE $YMPTR(INTEGER TYP,NUM);
RETURN(SYMBOL_TABLE[ARR0[TYP]+NUM]);
DEFINE $YMREF(I,J)=⊂SYMBOL_TABLE[ARR0[I]+J]⊃;
! recover;
! called when an indefined variable is used. Tries to recover, asking
the correct name of the variable, and returns it.
(null string or <control-C> to return to the main loop);
STRING PROCEDURE RECOVER(STRING SYMB);
BEGIN "R"
STRING ANSWER;LABEL CC;
! you can change the identifier symb;
CC:
LODED(SYMB&CR);
ANSWER←INCHWL; ! reads new identifier;
IFC #OUTPT THENC
IF $OUT THEN CPRINT($TTYCH,ANSWER,CRLF);
ENDC
SYMB←SCAN(ANSWER,$ERRTAB,$BRCHR); ! eliminates blanks and checks break;
IF $BRCHR≠0 AND $BRCHR≠'40
THEN BEGIN
PRINT("break character found. Try again ");
GO TO CC; ! so... you can try again;
END
ELSE IF SYMB THEN RETURN(SYMB); ! a "good" symbol is returned;
! you want to delete the instruction being interpreted;
CLRBUF;
IFC #DISPL THENC
IF DEVICE≠DSK_X THEN $ALLOW←0; ! while reading display is not updated;
ENDC
ESC_P;
ERROR("instruction not executed",CRLF);
END "R";
! symbol table: check,checktot,ensym,delsym,newsym,oldsym;
! checks if symbol symb, of type nm, is in symbol table in the class nm,
and return its pointer;
RPTR(SYMBOL)PROCEDURE CHCK(STRING SYMB; INTEGER TYPE; REFERENCE INTEGER COUNTER);
BEGIN
! checks for symbol SYMB as data type TYPE, and changes COUNTER
to the entry in the symbol table;
RPTR(SYMBOL)TEMP; INTEGER IND;
IND←$ENTRY[TYPE]; ! address of last record of type TYPE filled ;
FOR COUNTER←1 STEP 1 UNTIL IND DO
IF (TEMP←$YMPTR(TYPE,COUNTER)) AND EQU(SYMBOL:PNAME[TEMP],SYMB)
THEN RETURN(TEMP);
COUNTER←0;
RETURN(NULL_RECORD);
END;
INTERNAL RPTR(SYMBOL) PROCEDURE CHECK(STRING SYMB;INTEGER TYPE);
BEGIN
! checks if SYMB is an identifier of type TYPE ;
INTEGER I;
RETURN(CHCK(SYMB,TYPE,I));
END;
! checks if symbol symb is in symbol table, determines its class and
return its pointer;
RPTR(SYMBOL)PROCEDURE CHCKTOT(STRING SYMB; REFERENCE INTEGER TYPE,COUNTER);
BEGIN
INTEGER TYPE,COUNTER;RPTR(SYMBOL)TEMP;
FOR TYPE←#MIN STEP 1 UNTIL #MAX DO
IF (TEMP←CHCK(SYMB,TYPE,COUNTER)) THEN RETURN(TEMP);
TYPE←0;
RETURN(NULL_RECORD); ! symbol not found;
END;
INTERNAL RPTR(SYMBOL) PROCEDURE CHECKTOT(STRING SYMB);
BEGIN INTEGER I,J;
RETURN(CHCKTOT(SYMB,I,J));
END;
INTERNAL BOOLEAN PROCEDURE UNDECLARED(STRING NAME);
RETURN(IF CHECKTOT(NAME)=NULL_RECORD THEN TRUE ELSE FALSE);
! given an array element returns the name of the array;
INTERNAL STRING PROCEDURE ARNAME(STRING EL_NAME);
BEGIN
INTEGER I,BR;STRING TEMP;
SETBREAK(I←GETBREAK,"[",NULL,"IS");
TEMP←SCAN(EL_NAME,I,BR); RELBREAK(I);
RETURN(TEMP);
END;
! return the symbol pointer. If EL_NAME is an array element return the pointer to
the array in the symbol table;
INTERNAL RPTR(SYMBOL)PROCEDURE $YM_PTR(STRING EL_NAME);
RETURN(CHECKTOT(ARNAME(EL_NAME)));
! return the symbol pointer of NAME. If NAME is an array element return the pointer
to the array element (taken from ARRAYREC:PTR);
INTERNAL RPTR(SYMBOL)PROCEDURE SYM_PTR_OF(STRING NAME);
BEGIN
RPTR(SYMBOL) SYMB;RPTR(ARRAYREC)ARR;
IF (SYMB←$YM_PTR(NAME))=NULL_RECORD
THEN RETURN(SYMB)
ELSE BEGIN
CASE SYMBOL:ACCESS[SYMB] OF BEGIN "case"
[#SIMPLE] [#PROCEDURE] RETURN(SYMB);
[#ARRAY] BEGIN
INTEGER #DIM,I,J,BR;STRING AR_PARAM;
AR_PARAM←NAME[LENGTH(SYMBOL:PNAME[SYMB])+1 TO ∞];
#DIM←ARRAYREC:#DIM[ARR←SYMBOL:OBJECT[SYMB]];J←0;
FOR I←1 STEP 1 UNTIL #DIM DO
J←J+(INTSCAN(AR_PARAM,BR)-ARRAYREC:LB[ARR][I])
*ARRAYREC:MUL[ARR][I];
RETURN(ARRAYREC:PTR[ARR][J+1]);
END;
[#ARRAY_ELEMENT] ERROR("ERROR in SYMBOL TABLE: #ARRAY ELEMENT found")
end "case";
END;
END;
! enters the symbol symb and the pointer to its node in symbol table,
in the class nm. The record of the class SCALAR,VECTOR,ROT,TRANS or
FRAME has to be constructed before calling ENSYM;
INTEGER PROCEDURE NEW_OFFSET(INTEGER NM);
BEGIN
INTEGER I;
IF NM≠#MC THEN
IF OFFSET[CUR_OFFSET,NM]=ARR1[NM]
THEN ERROR("NO MORE SPACE FOR NEW SYMBOLS IN 11");
CASE NM OF
BEGIN
[#SC][#VT][#EV][#ST][#MC]
OFFSET[CUR_OFFSET,NM]←OFFSET[CUR_OFFSET,NM]+1;
[#RT][#TR][#FR]
FOR I← 3 STEP 1 UNTIL 5 DO OFFSET[CUR_OFFSET,I]←OFFSET[CUR_OFFSET,I]+1;
[#PR][#CM] I←I
END;
RETURN(OFFSET[CUR_OFFSET,NM]);
END;
INTERNAL RPTR(SYMBOL) PROCEDURE ENSYM(STRING SYMB;INTEGER NM;RANY VAL;
RPTR(SYMBOL)OLDREC(NULL_RECORD); INTEGER ACCESS(#SIMPLE));
BEGIN
RPTR (SYMBOL) TEMP;INTEGER IND;
IF $ENTRY[NM]≥ARR1[NM]
THEN ERROR("insufficient space in symbol table");
IF OLDREC THEN TEMP←OLDREC ELSE TEMP←NEW_RECORD(SYMBOL);
$YMREF(NM,($ENTRY[NM]←$ENTRY[NM]+1))←TEMP; ! pointer to the new record
in SYMBOL TABLE ;
! SYMBOL:VALID[TEMP]←TRUE;
SYMBOL:TYPE[TEMP]←NM;
SYMBOL:PNAME[TEMP]←SYMB; ! pname of symbol;
SYMBOL:OBJECT[TEMP]←VAL; ! pointer to the record previously created;
IF ACCESS=#SIMPLE AND #MIN≤NM≤#BASIC_TYPES THEN
BEGIN SYMBOL:INDEX[TEMP]←NEW_OFFSET(NM);
SYMBOL:OFFSET[TEMP]←ARROFF[NM];
END
ELSE IF NM=#MC THEN SYMBOL:INDEX[TEMP]←NEW_OFFSET(NM);
RETURN(TEMP);
END;
INTERNAL PROCEDURE ENSYM$(RPTR(SYMBOL)SYM; INTEGER NM(0));
BEGIN
INTEGER IND;
IF NM=0 THEN NM←SYMBOL:TYPE[SYM] ELSE SYMBOL:TYPE[SYM]←NM;
IF $ENTRY[NM]≥ARR1[NM]
THEN ERROR("insufficient space in symbol table");
IF NM=#FR AND SYMBOL:ACCESS[SYM]=#SIMPLE
THEN IF SYM≠ WORLD THEN LINKFR(SYMBOL:OBJECT[SYM],F_WRLD);
$YMREF(NM,($ENTRY[NM]←$ENTRY[NM]+1))←SYM; ! pointer to the new record in $YMTAB;
IF SYMBOL:ACCESS[SYM]=#SIMPLE AND #MIN≤NM≤#BASIC_TYPES THEN
BEGIN SYMBOL:INDEX[SYM]←NEW_OFFSET(NM);
SYMBOL:OFFSET[SYM]←ARROFF[NM];
END
ELSE IF (NM=#MC) OR (NM=#CM) THEN SYMBOL:INDEX[SYM]←NEW_OFFSET(NM);
END;
! returns a new symbol, if symb is present in SYMBOL TABLE.
Id used before
inserting a new symbol in SYMBOL TABLE to be sure that a symbol with the
name has not been defined before. This procedure allows recovering;
INTERNAL STRING PROCEDURE NEWSYM(STRING SYMB);
BEGIN
RPTR(SYMBOL)TEMP;
! if there is a symbol with the same pname allows recovering;
WHILE (TEMP←CHECKTOT(SYMB))≠NULL_RECORD
DO BEGIN
PRINT(SYMB," has already been defined");
SYMB←RECOVER(SYMB);
END;
RETURN(SYMB);
END;
! checks if symb is present in SYMBOL TABLE
and returns its pointer and its
type (using the reference variable obtype), otherwise allows recovering.
Is used when the symbol required has to be present in SYMBOL TABLE
(ex. in EDIT or RENAME instruction);
INTERNAL RPTR(SYMBOL) PROCEDURE OLDSYM(REFERENCE STRING SYMB;REFERENCE INTEGER OBTYPE);
BEGIN
RPTR(SYMBOL)EL;
EL←CHECKTOT(SYMB);
! if symbol is not in SYMBOL TABLE, recovering is allowed;
WHILE (EL←CHECKTOT(SYMB))=NULL_RECORD
DO BEGIN
PRINT(" object not existent ");
SYMB←RECOVER(SYMB);
END;
OBTYPE←SYMBOL:TYPE[EL];
RETURN(EL);
END;
INTERNAL PROCEDURE DELSYM(RPTR(SYMBOL)EL);
BEGIN
INTEGER ADDRFN,I;
INTEGER OBTYPE; OBTYPE←SYMBOL:TYPE[EL];
ADDRFN← $ENTRY[OBTYPE]; ! final addr. in $YMTAB for class;
FOR I←1 STEP 1 UNTIL ADDRFN DO
IF $YMPTR(OBTYPE,I)=EL
THEN BEGIN
$YMREF(OBTYPE,I)←$YMPTR(OBTYPE,ADDRFN);
$ENTRY[OBTYPE]←ADDRFN-1; ! move last element into hole;
! SYMBOL:VALID[EL]←FALSE;
DONE;
END;
END;
! symbol table: mk_pr, mk_rec, mk_sym, symtree routines;
! produces a symbol record with certain fields filled in ;
INTERNAL RPTR(SYMBOL)PROCEDURE MK_SYM(STRING PNAME; INTEGER TYPE;
RANY PTR(NULL_RECORD); INTEGER ACCESS(#SIMPLE));
BEGIN
RPTR(SYMBOL)SYM;
SYM←NEW_RECORD(SYMBOL);
SYMBOL:PNAME[SYM]←PNAME;
SYMBOL:TYPE[SYM]←TYPE;
SYMBOL:OBJECT[SYM]←PTR;
SYMBOL:ACCESS[SYM]←ACCESS;
RETURN(SYM);
END;
INTERNAL RPTR(PROC)PROCEDURE MK_PR(INTEGER ARGS; STRING ARRAY ARGNAME;
INTEGER ARRAY ARGTYPE,ARGACCS,ARGDIM);
IF ARGS=0 THEN RETURN(NEW_RECORD(PROC)) ELSE
BEGIN
RPTR(PROC)E;
STRING ARRAY S[1:ARGS];
INTEGER ARRAY T,C,D[1:ARGS];
ARRTRAN(S,ARGNAME);
ARRTRAN(T,ARGTYPE);
ARRTRAN(C,ARGACCS);
ARRTRAN(D,ARGDIM);
E←NEW_RECORD(PROC);
PROC:NARGS[E]←ARGS;
MEMORY[LOCATION(PROC:ARGNAME[E])]↔MEMORY[LOCATION(S)];
MEMORY[LOCATION(PROC:ARGDIM[E])]↔MEMORY[LOCATION(D)];
MEMORY[LOCATION(PROC:ARGACCS[E])]↔MEMORY[LOCATION(C)];
MEMORY[LOCATION(PROC:ARGTYPE[E])]↔MEMORY[LOCATION(T)];
RETURN(E);
END;
INTERNAL RPTR(SCALAR,VECTOR,ROT,TRANS,FRAME,CMON,PSTRING) PROCEDURE MK_REC(INTEGER TYPE);
BEGIN
RANY TEMP;
REAL ARRAY XF[1:6];
CASE TYPE OF
begin "case"
[#SC] TEMP←NEW_RECORD(SCALAR);
[#VT] TEMP←NEW_RECORD(VECTOR);
[#RT] BEGIN
TEMP←NEW_RECORD(ROT);
MEMORY[LOCATION(ROT:XF[TEMP])]←MEMORY[LOCATION(XF)];
END;
[#TR] BEGIN
TEMP←NEW_RECORD(TRANS);
MEMORY[LOCATION(TRANS:XF[TEMP])]←MEMORY[LOCATION(XF)];
END;
[#FR] BEGIN
TEMP←NEW_RECORD(FRAME);
MEMORY[LOCATION(FRAME:XF[TEMP])]←MEMORY[LOCATION(XF)];
! insert here the affixment to the world;
FRAME:HOWLINKED[TEMP]←#INDLK; ! independently;
END;
! [#MC] TEMP←NEW_RECORD(MACRO);
[#FN] TEMP←NEW_RECORD(PROC);
[#EV] TEMP← NULL_RECORD; ! No record needed for EVENTs;
[#CM] TEMP←NEW_RECORD(CMON);
[#ST] TEMP←NEW_RECORD(PSTRING);
ELSE ERROR("PARSER ERROR, NO SUCH RECORD CLASS IN MK_REC")
end "case";
MEMORY[LOCATION(XF)]←0;
RETURN(TEMP);
END;
RPTR(SYMTREE)PROCEDURE MK_SYMTREE(RPTR(SYMBOL)S);
BEGIN
RPTR(SYMTREE)E;
SYMTREE:SYM[E←NEW_RECORD(SYMTREE)]←S;
RETURN(E);
END;
RECURSIVE PROCEDURE INSRTTREE(RPTR(SYMBOL)S; RPTR(SYMTREE)STREE);
BEGIN
RPTR(SYMTREE)SS;
CASE COMPEQU(SYMBOL:PNAME[S],SYMBOL:PNAME[SYMTREE:SYM[STREE]])+1 OF
BEGIN
[-1+1] IF (SS←SYMTREE:LLINK[STREE])=NULL_RECORD
THEN SYMTREE:LLINK[STREE]←MK_SYMTREE(S)
ELSE INSRTTREE(S,SS);
[0+1] ERROR("ugh trying to insert element ");
[1+1] IF (SS←SYMTREE:RLINK[STREE])=NULL_RECORD
THEN SYMTREE:RLINK[STREE]←MK_SYMTREE(S)
ELSE INSRTTREE(S,SS)
END;
END;
INTERNAL PROCEDURE INSRTSYMTREE(RPTR(SYMBOL)S;RPTR(BLOCKREC)STREE);
BEGIN
IF BLOCKREC:TREE[STREE]=NULL_RECORD
THEN BLOCKREC:TREE[STREE]←MK_SYMTREE(S)
ELSE INSRTTREE(S,BLOCKREC:TREE[STREE]);
BLOCKREC:#ARGS[STREE]←BLOCKREC:#ARGS[STREE]+1;
END;
INTERNAL RPTR(BLOCKREC)PROCEDURE BLOCKIFY(INTEGER NARGS; RPTR(SYMBOL)ARRAY SYMARR;
RPTR(BLOCKREC)BLOCK(NULL_RECORD));
BEGIN INTEGER I;
RPTR(BLOCKREC)BLOCKPTR;
IF BLOCK THEN BLOCKPTR←BLOCK ELSE BLOCKPTR←NEW_RECORD(BLOCKREC);
FOR I←1 STEP 1 UNTIL NARGS DO
INSRTSYMTREE(SYMARR[I],BLOCKPTR);
RETURN(BLOCKPTR);
END;
RPTR(SYMBOL)RECURSIVE PROCEDURE SEARCHSYMTREE(STRING S; RPTR(SYMTREE)STREE);
IF STREE=NULL_RECORD
THEN RETURN(NULL_RECORD)
ELSE CASE COMPEQU(S,SYMBOL:PNAME[SYMTREE:SYM[STREE]]) +1 OF
BEGIN
[-1+1] RETURN(SEARCHSYMTREE(S,SYMTREE:LLINK[STREE]));
[0+1] RETURN(SYMTREE:SYM[STREE]);
[1+1] RETURN(SEARCHSYMTREE(S,SYMTREE:RLINK[STREE]))
END;
INTERNAL RPTR(SYMBOL)PROCEDURE SEARCHBLOCK(STRING S; RPTR(BLOCKREC)R);
RETURN(SEARCHSYMTREE(S,BLOCKREC:TREE[R]));
RPTR(SYMBOL)RECURSIVE PROCEDURE SEARCHSYMTREEOFF(INTEGER I; RPTR(SYMTREE)STREE);
IF STREE=NULL_RECORD
THEN RETURN(NULL_RECORD)
ELSE IF I=SYMBOL:OFFSET[SYMTREE:SYM[STREE]]
THEN RETURN(SYMTREE:SYM[STREE])
ELSE BEGIN
RPTR(SYMBOL)S;
IF S←SEARCHSYMTREEOFF(I,SYMTREE:LLINK[STREE])
THEN RETURN(S)
ELSE RETURN(SEARCHSYMTREEOFF(I,SYMTREE:RLINK[STREE]))
END;
RPTR(SYMBOL)PROCEDURE SEARCHBLOCKOFF(INTEGER I; RPTR(BLOCKREC)R);
IF R THEN RETURN(SEARCHSYMTREEOFF(I,BLOCKREC:TREE[R]))
ELSE RETURN(NULL_RECORD);
! symbol table: gtframe,checkoff,arrydim;
INTERNAL RPTR(FRAME) PROCEDURE GTFRAME(INTEGER LEVOFF,#DIM; INTEGER ARRAY DIM;
RPTR(SYMBOL)S);
IF LEVOFF=ARROFF[#FR] THEN
BEGIN
RPTR(SYMBOL)TEMP;
INTEGER I;
FOR I←1 STEP 1 UNTIL $ENTRY[#FR] DO
IF DIM[1]=SYMBOL:INDEX[TEMP←$YMPTR(#FR,I)] THEN
RETURN(SYMBOL:OBJECT[TEMP]);
RETURN(NULL_RECORD);
END
ELSE BEGIN "array or temporary"
! not quite reight, this only assumes arrays;
RPTR(ARRAYREC)ARR;
INTEGER I,J;
IF NOT S THEN ERROR("ERROR n GTFRAME: cant handle temporary variables yyet");
ARR←SYMBOL:OBJECT[S];
J←0;
FOR I←1 STEP 1 UNTIL #DIM
DO J←J+(DIM[I]-ARRAYREC:LB[ARR][I])*ARRAYREC:MUL[ARR][I];
RETURN(SYMBOL:OBJECT[ARRAYREC:PTR[ARR][J+1]]);
END "array or temporary";
! returns the symbol for given offset;
INTERNAL RPTR(SYMBOL) PROCEDURE CHECKOFF(INTEGER LEVOFF);
BEGIN
RPTR(SYMBOL) TEMP; INTEGER I,J;
! REMEMBER TO TAKE CARE OF LOCAL VARIABLES;
IF CURBLOCK AND TEMP←SEARCHBLOCKOFF(LEVOFF,CURBLOCK) THEN RETURN(TEMP);
FOR I←#MIN STEP 1 UNTIL #MAX DO
FOR J←1 STEP 1 UNTIL $ENTRY[I]
DO IF (TEMP←$YMPTR(I,J)) AND SYMBOL:OFFSET[TEMP]=LEVOFF
THEN RETURN(TEMP);
RETURN(NULL_RECORD);
END;
! returns number of dimensions in symbol table for the leveloffset given;
INTERNAL INTEGER PROCEDURE ARRYDIM(INTEGER LEVOFF;REFERENCE RPTR(SYMBOL) SYM);
BEGIN
SYM←NULL_RECORD;
IF LEVOFF=ARROFF[#SC] OR LEVOFF=ARROFF[#VT] OR LEVOFF=ARROFF[#RT]
OR LEVOFF=ARROFF[#TR] OR LEVOFF=ARROFF[#FR]
THEN RETURN(1)
ELSE IF SYM←CHECKOFF(LEVOFF)
THEN IF SYMBOL:ACCESS[SYM]=#SIMPLE THEN RETURN(0)
ELSE RETURN(ARRAYREC:#DIM[SYMBOL:OBJECT[SYM]])
ELSE RETURN(0);
END;
! symbol table: nwr,dcdsym,unlink,linkfr,nwarec;
PROCEDURE UNLINK(RPTR(FRAME) N);
BEGIN
RPTR(FRAME) Y,E;
E←FRAME:EBRO[N];
IF (Y←FRAME:YBRO[N])≠NULL_RECORD
THEN FRAME:EBRO[Y]←E
ELSE IF FRAME:DAD[N]≠NULL_RECORD THEN FRAME:SON[FRAME:DAD[N]]←E;
IF E≠NULL_RECORD THEN FRAME:YBRO[E]←Y;
FRAME:EBRO[N]←NULL_RECORD;
FRAME:YBRO[N]←NULL_RECORD;
FRAME:DAD[N]←NULL_RECORD;
END;
BOOLEAN PROCEDURE IS_ANCESTOR(RPTR(FRAME) N,D);
BEGIN
WHILE N≠NULL_RECORD DO
IF N=D THEN RETURN(TRUE)
ELSE N←FRAME:DAD[N];
RETURN(FALSE);
END;
! sets #UP pointer structure in frame tree for N to be a child of D;
INTERNAL PROCEDURE LINKFR(RPTR(FRAME) N,D);
BEGIN
IF NOT(D=F_WRLD AND FRAME:HOWLINKED[N]=#INDLK)
THEN IF IS_ANCESTOR(D,N)
THEN ERROR(" backwards affixment to",frame:pname[D]);
IF FRAME:DAD[N]≠NULL_RECORD THEN UNLINK(N);
IF (FRAME:EBRO[N]←FRAME:SON[D])≠NULL_RECORD THEN
FRAME:YBRO[FRAME:EBRO[N]]←N;
FRAME:YBRO[N]←NULL_RECORD;
FRAME:DAD[N]←D;
FRAME:SON[D]←N;
END;
RPTR(TRANS) PROCEDURE ABSLOC(RPTR(FRAME) ND);
BEGIN
PRINT("DUMMY ABSLOC"); RETURN(NULL_RECORD); END;
RPTR(SYMBOL)PROCEDURE NWR(STRING SYMB; INTEGER TYP);
BEGIN
RPTR(SCALAR,VECTOR,ROT,TRANS,FRAME)VAL; RPTR(SYMBOL)TEMP;
SYMB←NEWSYM(SYMB);
VAL←MK_REC(TYP);
TEMP←ENSYM(SYMB,TYP,VAL);
IF TYP=#FR THEN BEGIN FRAME:PNAME[VAL]←SYMB;
IF TEMP≠ WORLD THEN LINKFR(VAL,F_WRLD);
FRAME:PNAME[VAL]←SYMB;
FRAME:HOWLINKED[VAL]←#INDLK;
FRAME:SYM[VAL]←TEMP;
END;
$DISPLAYLIST[TYP]←NULL;
RETURN(TEMP);
END;
! like nwr but does not insert into symbol table;
INTERNAL RPTR(SYMBOL)PROCEDURE NNWR(STRING SYMB; INTEGER TYP; INTEGER ACCESS(#SIMPLE));
BEGIN
RPTR(SCALAR,VECTOR,ROT,TRANS,FRAME,CMON)VAL; RPTR(SYMBOL)TEMP;
TEMP←MK_SYM(SYMB,TYP,VAL←MK_REC(TYP),ACCESS);
IF TYP=#FR THEN BEGIN
! the frame is affixed in ENSYM$;
FRAME:PNAME[VAL]←SYMB;
FRAME:HOWLINKED[VAL]←#INDLK;
FRAME:SYM[VAL]←TEMP;
END;
RETURN(TEMP);
END;
INTERNAL RPTR(SYMBOL)PROCEDURE NWAREC(RPTR(SYMBOL)TEMP;INTEGER #EL;
INTEGER ARRAY LB,UB,MULT);
BEGIN
RPTR(ARRAYREC)VAL;
INTEGER TYP,#DIM,OFFSET;
OFFSET←SYMBOL:OFFSET[TEMP];
VAL←SYMBOL:OBJECT[TEMP];
TYP←SYMBOL:TYPE[TEMP];
#DIM←ARRAYREC:#DIM[VAL];
BEGIN
INTEGER ARRAY ALB,AUB,MUL[1:5];
INTEGER ARRAY I[1:5];
INTEGER J,JJ;
STRING S1,S2;
RPTR(SYMBOL) ARRAY PTR[1:#EL];
ARRBLT(ALB[1],LB[1],#DIM);
ARRBLT(AUB[1],UB[1],#DIM);
ARRBLT(MUL[1],MULT[1],#DIM);
S1←SYMBOL:PNAME[TEMP]&"[";
JJ←0;
FOR I[1]←ALB[1] STEP 1 UNTIL AUB[1] DO
FOR I[2]←ALB[2] STEP 1 UNTIL AUB[2] DO
FOR I[3]←ALB[3] STEP 1 UNTIL AUB[3] DO
FOR I[4]←ALB[4] STEP 1 UNTIL AUB[4] DO
FOR I[5]←ALB[5] STEP 1 UNTIL AUB[5] DO
BEGIN
S2←S1&CVS(I[1]);
FOR J←2 STEP 1 UNTIL #DIM DO
S2←S2&","&CVS(I[J]);
S2←S2&"]";
SYMBOL:OFFSET[PTR[JJ←JJ+1]←NNWR(S2,TYP,#ARRAY_ELEMENT)]
← OFFSET;
IF TYP=#FR THEN
LINKFR(SYMBOL:OBJECT[PTR[JJ]],F_WRLD);
END;
ARRAYREC:#EL[VAL]←#EL;
MEMORY[LOCATION(ARRAYREC:PTR[VAL])]↔MEMORY[LOCATION(PTR)];
MEMORY[LOCATION(ARRAYREC:LB[VAL])]↔MEMORY[LOCATION(ALB)];
MEMORY[LOCATION(ARRAYREC:UB[VAL])]↔MEMORY[LOCATION(AUB)];
MEMORY[LOCATION(ARRAYREC:MUL[VAL])]↔MEMORY[LOCATION(MUL)];
END;
RETURN(TEMP);
END;
! symbol table: control,insertion,prdecl;
INTERNAL BOOLEAN PROCEDURE PRDECL(RPTR(SYMBOL) OB1);
IF SYMBOL:TYPE[OB1]=#PR OR SYMBOL:TYPE[OB1]=#MC OR SYMBOL:TYPE[OB1]=#EV
THEN RETURN(FALSE)
ELSE
RETURN((SYMBOL:OFFSET[OB1]<'400) OR
(OFFSET[PRG_OFFSET,SYMBOL:TYPE[OB1]]
<SYMBOL:INDEX[OB1]≤OFFSET[CON_OFFSET,SYMBOL:TYPE[OB1]]));
INTERNAL RPTR(SYMBOL)PROCEDURE CNVRTR(RPTR(SYMBOL)EL;STRING SYMB);
BEGIN
RPTR(TRANS) TEMP;RPTR(SYMBOL)EL2;
TEMP←SYMBOL:OBJECT[EL];
IF SYMBOL:OFFSET[EL]≥'1000
THEN ERROR("CANT convert trans to frame for local variables");
EL2←NNWR(SYMB,#FR);
ARRTRAN(FRAME:XF[SYMBOL:OBJECT[EL2]],TRANS:XF[TEMP]);
SYMBOL:INDEX[EL2]←SYMBOL:INDEX[EL];
SYMBOL:OFFSET[EL2]←SYMBOL:OFFSET[EL];
SYMBOL:ACCESS[EL2]←SYMBOL:ACCESS[EL];
DELSYM(EL); ! delete from symbol table;
$YMREF(#FR,($ENTRY[#FR]←$ENTRY[#FR]+1))←EL2;
$FRLST←$TRLST←NULL;
RETURN(EL2);
END;
! if the symbol symb is present in SYMBOL TABLE in the class OBTYPE returns
the pointer to it, otherwise allows recovering. The symbol is passed
by reference so after recovering the new symbol is sent back;
RPTR(SYMBOL) PROCEDURE BELONGS2(REFERENCE STRING SYMB;INTEGER OBTYPE);
BEGIN
RPTR(SYMBOL) EL;
EL←CHECK(SYMB,OBTYPE); ! checks if symbol is present;
WHILE EL=NULL_RECORD
DO BEGIN
IF OBTYPE=#FR
THEN BEGIN
EL←CHECK(SYMB,#TR);
IF EL
THEN BEGIN
EL←CNVRTR(EL,SYMB);
RETURN(EL);
END;
END;
PRINT($DTYPE[OBTYPE]&" required");
SYMB←RECOVER(SYMB); ! recover can interrupt the loop and abort;
EL←CHECK(SYMB,OBTYPE);
END;
RETURN(EL); ! returns the pointer to the symbol;
END;
INTERNAL RANY PROCEDURE BELONGS(REFERENCE STRING SYMB; INTEGER OBTYPE);
RETURN(SYMBOL:OBJECT[BELONGS2(SYMB,OBTYPE)]);
! checks if the symbol (scalar,vector or rotation) is in SYMBOL TABLE
If not inserts it, and returns its pointer;
INTERNAL RPTR(SYMBOL) PROCEDURE INSERT(STRING SYMB;INTEGER OBTYPE);
BEGIN
RPTR(SYMBOL)EL;
IF OBTYPE=#FR THEN
BEGIN RPTR(FRAME)FR1; STRING S1;
S1←SYMB;
FR1←FR_INSERT(S1);
RETURN(CHECK(S1,OBTYPE));
END;
EL←CHECK(SYMB,OBTYPE);
IF EL=NULL_RECORD THEN EL←NWR(SYMB,OBTYPE);
RETURN(EL);
END;
! returns the pointer to the frame. If the frame is not present inserts it,
otherwise checks its affixment type and asks for a confirmation if
the affixment type is not independent. In that case recovering is allowed;
INTERNAL RPTR(FRAME) PROCEDURE FR_INSERT (REFERENCE STRING SYMB);
BEGIN "A"
RPTR(SYMBOL) EL;
RPTR(FRAME) FRA; STRING TEMP;INTEGER LINK;
WHILE TRUE
DO BEGIN "LOOP"
EL←CHECK(SYMB,#FR); ! if while copying;
WHILE EL≠NULL_RECORD
DO BEGIN
! while copying a new frame is required.
Recovering is allowed if the frame is existent;
PRINT("symbol has already been defined");
SYMB←RECOVER(SYMB);
EL←CHECK(SYMB,#FR);
END;
IF EL=NULL_RECORD
THEN BEGIN
EL←CHECK(SYMB,#TR);
IF EL THEN EL←CNVRTR(EL,SYMB)
ELSE EL←NWR(SYMB,#FR); ! defines a new frame;
RETURN(SYMBOL:OBJECT[EL]);
END
ELSE BEGIN "C"
FRA←SYMBOL:OBJECT[EL];
LINK←FRAME:HOWLINKED[FRA];
! changing values of the frame is allowed if link is #INDLK;
IF LINK=#INDLK
THEN BEGIN
$FRLST←NULL;
RETURN(FRA);
END
ELSE BEGIN
! otherwise a confirmation is required;
PRINT(SYMB,
" affixed frame. Changing values can modify the frame tree.",CRLF,
"You can change the name ");
TEMP←RECOVER(SYMB);
! if the name of the frame is the same,
changing values is allowed;
IF EQU(TEMP ,SYMB)
THEN BEGIN
$FRLST←NULL;
RETURN(FRA);
END
ELSE SYMB←TEMP;
END;
END "C";
END "LOOP";
END "A";
! symbol table: killtree,killvar,reset;
! removes from SYMBOL TABLE all nodes in the subtrees rooted at el;
RECURSIVE PROCEDURE KILLTREE (RPTR(SYMBOL) EL);
BEGIN
RPTR(FRAME)TEMP; RPTR(SYMBOL)E;
TEMP←SYMBOL:OBJECT[E←EL];
DELSYM(EL); ! removes el from $YMTAB;
TEMP←FRAME:SON[TEMP];
WHILE TEMP≠NULL_RECORD DO
BEGIN
EL←CHECK(FRAME:PNAME[TEMP],#FR);
KILLTREE(EL);
TEMP←FRAME:EBRO[TEMP];
END;
END;
! removes the symbol from SYMBOL TABLE ;
INTERNAL PROCEDURE KILLVAR(RPTR(SYMBOL)EL);
BEGIN ! before calling this routine make sure that you are not deleting a pointy declared variable ;
IF SYMBOL:TYPE[EL]≠#FR
THEN DELSYM(EL)
ELSE BEGIN
IF SYMBOL:ACCESS[EL]≠#SIMPLE THEN
ERROR("Can only kill simple frames unless you kill all frames");
UNLINK(SYMBOL:OBJECT[EL]); ! unfixes the frame;
KILLTREE(EL); ! deletes subtrees rooted in var;
END;
$DISPLAYLIST[SYMBOL:TYPE[EL]]←NULL;
END;
! the procedure deletes all the variables defined by the user. It's
called by DELETE with no arguments.;
INTERNAL PROCEDURE RESET;
BEGIN
INTEGER IND,TEMP; RPTR(SYMBOL)EL;
! frames are handled differently because of the affixment;
IND←$ENTRY[#FR];
FOR TEMP←OFFSET[RES_OFFSET,#FR]+1 STEP 1 UNTIL IND DO
CASE SYMBOL:ACCESS[EL←$YMPTR(#FR,TEMP)] OF
BEGIN
[#SIMPLE] UNLINK(SYMBOL:OBJECT[EL]);
[#ARRAY]
BEGIN ! must be array;
RPTR(ARRAYREC)A;
INTEGER I;
A←SYMBOL:OBJECT[EL];
FOR I←1 STEP 1 UNTIL ARRAYREC:#EL[A] DO
UNLINK(SYMBOL:OBJECT[ARRAYREC:PTR[A][I]]);
END;
[#PROCEDURE] ;
ELSE
END;
FOR IND←#MIN STEP 1 UNTIL #MAX DO
BEGIN
$ENTRY[IND]←OFFSET[RES_OFFSET,IND];
$DISPLAYLIST[IND]←NULL;
END;
END;
! affixes the frame pointed by n to the frame pointed by d, as indicated
by how;
INTERNAL PROCEDURE AFX_NODE(RPTR(FRAME)N,D;INTEGER HOW);
BEGIN
LINKFR(N,D); ! sets links in frame tree;
FRAME:HOWLINKED[N]←HOW;
END;
INTERNAL PROCEDURE UFX_NODE(RPTR(FRAME)EL1,EL2);
BEGIN
UNLINK(EL1); ! breaks links in tree;
FRAME:HOWLINKED[EL1]←#INDLK;
LINKFR(EL1,F_WRLD); ! sets new links;
END;
END "SYMBOL";